package com.lyh.quartz.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lyh.common.core.domain.entity.SysUser;
import com.lyh.common.enums.OperationOriginEnum;
import com.lyh.common.enums.OperationStatusEnum;
import com.lyh.common.enums.OperationTypeEnum;
import com.lyh.common.utils.DateUtils;
import com.lyh.common.utils.StringUtils;
import com.lyh.system.domain.*;
import com.lyh.system.mapper.*;
import com.lyh.system.service.IAssetService;
import com.lyh.system.service.IMemberPurchaseInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static com.lyh.common.enums.RebateRuleEnum.*;

/**
 * 定时任务调度测试
 *
 * @author ruoyi
 */
//本地跑代码连服务端数据库时，先把定时任务这个注释掉，不然会多跑一遍结算数据
@Component("lyhTask")
@Transactional(rollbackFor = Exception.class)
public class LyhTask {

    @Autowired
    private MemberPurchaseInfoMapper memberPurchaseInfoMapper;
    @Autowired
    private AssetEvidenceMapper assetEvidenceMapper;
    @Autowired
    private SysAreaOrderMapper sysAreaOrderMapper;
    @Autowired
    private AssetMapper assetMapper;
    @Autowired
    private OperationInfoMapper operationInfoMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private UserRebatesMapper userRebatesMapper;
    @Autowired
    private IAssetService assetService;
    @Autowired
    private IMemberPurchaseInfoService memberPurchaseInfoService;

    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) {
        System.out.println(StringUtils.format("执行多参方法： 字符串类型{}，布尔类型{}，长整型{}，浮点型{}，整形{}", s, b, l, d, i));
    }

    public void ryParams(String params) {
        System.out.println("执行有参方法：" + params);
    }

    public void ryNoParams() {
        System.out.println("执行无参方法");
    }

    /**
     * 返佣：精确到返佣的小时内，如
     */


    public void reserveEvidences() {

        System.out.println("<===============预约报单每日结算=================>");

        //使用Calendar的getTime方法获取当前日期
        Calendar c = Calendar.getInstance();
//        c.add(Calendar.DATE, 7);//2、3、5、7
        String twoDaysAgoDate = DateUtils.parseDateToStr("yyyy-MM-dd HH", c.getTime());

        //审核通过 + 时间超出应结算时间(时间小于当前时间)
        List<MemberPurchaseInfo> memberPurchaseInfoList = memberPurchaseInfoMapper.selectList(new LambdaQueryWrapper<MemberPurchaseInfo>()
                .eq(MemberPurchaseInfo::getStatus, 1)
                .eq(MemberPurchaseInfo::getIntervalNextTime, twoDaysAgoDate));

        if (memberPurchaseInfoList.size() > 0) {
            for (MemberPurchaseInfo memberPurchaseInfo : memberPurchaseInfoList) {
                BigDecimal assetEvidenceNum = memberPurchaseInfo.getAssetEvidenceNum();

                AssetEvidence assetEvidence = assetEvidenceMapper.selectById(memberPurchaseInfo.getAssetEvidenceId());
                if (assetEvidence != null) {
                    QueryWrapper<SysAreaOrder> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("area_type", assetEvidence.getArea());
                    SysAreaOrder areaOrder = sysAreaOrderMapper.selectOne(queryWrapper);
                    BigDecimal incomeRate = new BigDecimal("1");
                    if (memberPurchaseInfo.getTimeInterval() == 2) {
                        if (areaOrder.getTwoNum() != null) {
                            incomeRate = incomeRate.multiply(areaOrder.getTwoNum()).multiply(new BigDecimal("0.01"));
                        }
                    } else if (memberPurchaseInfo.getTimeInterval() == 3) {
                        if (areaOrder.getThirdNum() != null) {
                            incomeRate = incomeRate.multiply(areaOrder.getThirdNum()).multiply(new BigDecimal("0.01"));
                        }
                    } else if (memberPurchaseInfo.getTimeInterval() == 5) {
                        if (areaOrder.getFiveNum() != null) {
                            incomeRate = incomeRate.multiply(areaOrder.getFiveNum()).multiply(new BigDecimal("0.01"));
                        }
                    } else if (memberPurchaseInfo.getTimeInterval() == 7) {
                        if (areaOrder.getSevenNum() != null) {
                            incomeRate = incomeRate.multiply(areaOrder.getSevenNum()).multiply(new BigDecimal("0.01"));
                        }
                    }
                    //收益金额
                    BigDecimal multiply = assetEvidenceNum.multiply(incomeRate);

                    //应打款金额
                    BigDecimal income = multiply.add(assetEvidenceNum);
                    Asset asset = assetMapper.selectAssetByUserId(memberPurchaseInfo.getUserId());
                    if (asset != null && asset.getEquityLimit() != null && asset.getEquityLimit().compareTo(new BigDecimal("0")) >= 0) {
                        BigDecimal subtract = asset.getEquityLimit().subtract(multiply);

                        OperationInfo oi = new OperationInfo();
                        oi.setUserId(memberPurchaseInfo.getUserId());
                        oi.setType(OperationTypeEnum.ASSET_EVIDENCE.name());
                        oi.setStatus(OperationStatusEnum.INCOME.name());
                        oi.setOperationTime(new Date());
                        oi.setOrigin(OperationOriginEnum.PURCHASE_INCOME.name());

                        if (subtract.compareTo(new BigDecimal("0")) >= 0) {
                            asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().add(income));
                            asset.setEquityLimit(subtract);
                            assetService.addOperationInfo(memberPurchaseInfo.getUserId(), OperationTypeEnum.EQUITY_LIMIT.name(),
                                    OperationStatusEnum.EXPENSE.name(), OperationOriginEnum.PURCHASE_INCOME.name(), multiply);
                            //添加收支记录
                            oi.setPrice(income);
                        } else {
                            asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().add(assetEvidenceNum).add(asset.getEquityLimit()));
                            oi.setPrice(assetEvidenceNum.add(asset.getEquityLimit()));
                            assetService.addOperationInfo(memberPurchaseInfo.getUserId(), OperationTypeEnum.EQUITY_LIMIT.name(),
                                    OperationStatusEnum.EXPENSE.name(), OperationOriginEnum.PURCHASE_INCOME.name(), asset.getEquityLimit());
                            asset.setEquityLimit(new BigDecimal("0"));

                        }
                        operationInfoMapper.insert(oi);
                        assetMapper.updateById(asset);
                    }
                }

                System.out.println("<===============预约报单立即释放比例返佣=================>");
                SysUser sysUser = sysUserMapper.selectById(memberPurchaseInfo.getUserId());
                if (sysUser.getParentId() != null) {
                    SysUser parentUser = sysUserMapper.selectById(sysUser.getParentId());
                    memberPurchaseInfoService.EndChangeReserveRebatesRule(parentUser, assetEvidenceNum, false, memberPurchaseInfo, sysUser, true);
                    memberPurchaseInfoService.allUserReserve(parentUser, assetEvidenceNum, memberPurchaseInfo, sysUser.getRebatesRate(), 0);
                }

                //更新状态
                memberPurchaseInfo.setStatus(3);
                memberPurchaseInfoMapper.updateById(memberPurchaseInfo);
            }
        }

        System.out.println("<===============预约报单每日释放比例返佣=================>");
        LambdaQueryWrapper<UserRebates> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(UserRebates::getResidueRebate, 0);
        List<UserRebates> userRebates = userRebatesMapper.selectList(queryWrapper);

        //添加收支记录
        OperationInfo info = new OperationInfo();
        info.setType(OperationTypeEnum.CONSUMER_COUPON.name());
        info.setStatus(OperationStatusEnum.INCOME.name());
        info.setOperationTime(new Date());
        info.setOrigin(OperationOriginEnum.RESERVE_EVIDENCE_INCOME.name());
        if (userRebates.size() > 0) {
            for (UserRebates userRebate : userRebates) {
                MemberPurchaseInfo memberPurchaseInfo = memberPurchaseInfoMapper.selectById(userRebate.getMemberPurchaseInfoId());
                BigDecimal timeInterval = new BigDecimal(memberPurchaseInfo == null ? 1 : memberPurchaseInfo.getTimeInterval());
                SysUser sysUser = sysUserMapper.selectById(userRebate.getUserId());
                Asset asset = assetMapper.selectAssetByUserId(sysUser.getUserId());

                BigDecimal ratio = new BigDecimal(0);

                //返回自身会员比例
                if (sysUser.getMemberLeve() != null && sysUser.getMemberLeve() > 0) {
                    if (SAME_LEVEL.equals(userRebate.getRebateRule())) {
                        ratio = memberPurchaseInfoService.getRatioByMemberLevel(sysUser.getMemberLeve());
                    } else if (SAME_LEVEL_02.equals(userRebate.getRebateRule())) {
                        ratio = new BigDecimal("0.00001");
                    } else if (HIGH_LEVEL.equals(userRebate.getRebateRule())) {
                        SysUser lowUser = sysUserMapper.selectById(userRebate.getLowUserId());
                        ratio = memberPurchaseInfoService.getRatioByMemberLevel(sysUser.getMemberLeve()).subtract(memberPurchaseInfoService.getRatioByMemberLevel(lowUser.getMemberLeve()));
                    }
                }
                BigDecimal decimal = userRebate.getAssetEvidenceNum().multiply(ratio).multiply(timeInterval);
                //添加收支记录(资产通证)
                OperationInfo oi = new OperationInfo();
                oi.setUserId(sysUser.getUserId());
                oi.setType(OperationTypeEnum.ASSET_EVIDENCE.name());
                oi.setStatus(OperationStatusEnum.INCOME.name());
                oi.setOperationTime(new Date());
                oi.setPrice(decimal);
                oi.setOrigin(OperationOriginEnum.RESERVE_EVIDENCE_INCOME.name());

                if (memberPurchaseInfo != null && memberPurchaseInfo.getResidueAssetEvidence() != null && memberPurchaseInfo.getResidueAssetEvidence().subtract(decimal).compareTo(new BigDecimal(0)) >= 0) {
                    if (userRebate.getResidueRebate().compareTo(decimal) >= 0) {
                        asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().add(decimal));
                        userRebate.setResidueRebate(userRebate.getResidueRebate().subtract(decimal));
                    } else {
                        asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().add(userRebate.getResidueRebate()));
                        userRebate.setResidueRebate(new BigDecimal(0));
                    }
                } else {
                    if (memberPurchaseInfo != null) {
                        asset.setAssetEvidenceNum(memberPurchaseInfo.getResidueAssetEvidence());
                        userRebate.setResidueRebate(new BigDecimal(0));
                    }

                }
                userRebate.setRebateTime(new Date());

                if (oi.getPrice().compareTo(new BigDecimal(0)) != 0) {
                    operationInfoMapper.insert(oi);
                }
                assetMapper.updateById(asset);
                userRebatesMapper.updateById(userRebate);

            }
        }
    }

    /**
     * 12：00 执行 未审核默认拒绝
     */
    public void updatePurchaseStatus() {
        System.out.println("<===============定时器每天拒绝预约=================>");

        //审核拒绝
        LambdaQueryWrapper<MemberPurchaseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MemberPurchaseInfo::getStatus, 0);
        List<MemberPurchaseInfo> memberPurchaseInfoList = memberPurchaseInfoMapper.selectList(wrapper);
        if (memberPurchaseInfoList.size() > 0) {
            for (MemberPurchaseInfo memberPurchaseInfo : memberPurchaseInfoList) {
                memberPurchaseInfo.setStatus(2);
                memberPurchaseInfo.setUpdateBy("定时器拒绝");
                memberPurchaseInfo.setAuditTime(new Date());//审核时间
                memberPurchaseInfoMapper.updateById(memberPurchaseInfo);
                //退钱
                Asset asset = assetMapper.selectAssetByUserId(memberPurchaseInfo.getUserId());
                asset.setAssetEvidenceNum(asset.getAssetEvidenceNum().add(memberPurchaseInfo.getAssetEvidenceNum()));
                asset.setConsumerCouponNum(asset.getConsumerCouponNum().add(memberPurchaseInfo.getConsumerCouponNum()));
                asset.setUpdateTime(new Date());
                assetMapper.updateById(asset);

                //添加收支记录(资产通证)
                OperationInfo oi = new OperationInfo();
                oi.setUserId(memberPurchaseInfo.getUserId());
                oi.setType(OperationTypeEnum.ASSET_EVIDENCE.name());
                oi.setStatus(OperationStatusEnum.INCOME.name());
                oi.setOperationTime(new Date());
                oi.setPrice(memberPurchaseInfo.getAssetEvidenceNum());
                oi.setOrigin(OperationOriginEnum.RESERVE_EVIDENCE.name());
                operationInfoMapper.insert(oi);

                //添加收支记录(消费券)
                OperationInfo oi1 = new OperationInfo();
                oi1.setUserId(memberPurchaseInfo.getUserId());
                oi1.setType(OperationTypeEnum.ASSET_EVIDENCE.name());
                oi1.setStatus(OperationStatusEnum.INCOME.name());
                oi1.setOperationTime(new Date());
                oi1.setType(OperationTypeEnum.CONSUMER_COUPON.name());
                oi1.setPrice(memberPurchaseInfo.getConsumerCouponNum());
                oi1.setOrigin(OperationOriginEnum.RESERVE_EVIDENCE.name());
                operationInfoMapper.insert(oi1);
            }
        }
    }

    public void memberLevelUpRule() {
        System.out.println("==========会员升级检查===========");

        up(0, 5, 1);
        directAndIndirectUp(5, 49, 2);
        directAndIndirectUp(9, 99, 3);
        directAndIndirectUp(12, 149, 4);
        directAndIndirectUp(15, 499, 5);

    }

    //升级规则
    private void directAndIndirectUp(Integer directMemberNum, Integer allInviteUserNum, Integer rightMemberLevel) {
        List<SysUser> directUpUsers = sysUserMapper.upgradeUser(1, directMemberNum, rightMemberLevel);

        for (SysUser sysUser : directUpUsers) {
            int upNum = 0;
            int residueIndirect = allInviteUserNum - sysUser.getInviteNum();
            if (residueIndirect <= 0) {
                if (sysUser.getRebatesFlag() == 0) {
                    sysUser.setMemberLeve(rightMemberLevel);
                    sysUserMapper.updateById(sysUser);
                }
            } else {
                String indirectInviteCodes = sysUser.getIndirectInviteCodes();
                List<SysUser> sysUserList = sysUserMapper.myIndirectUser(indirectInviteCodes);
                for (SysUser user : sysUserList) {
                    if (user.getMemberLeve() != null) {
                        if (user.getMemberLeve() >= 1) {
                            upNum++;
                        }
                    }
                }
                if (upNum >= residueIndirect) {
                    if (sysUser.getRebatesFlag() == 0) {
                        sysUser.setMemberLeve(rightMemberLevel);
                        sysUserMapper.updateById(sysUser);
                    }
                }
            }

        }

    }


    //直推升级
    private void up(Integer lowMemberLevel, Integer memberNum, Integer rightMemberLevel) {
        List<SysUser> sysUsers = sysUserMapper.zeroUpOne(lowMemberLevel, memberNum, rightMemberLevel);
        if (sysUsers != null && sysUsers.size() > 0) {
            for (SysUser sysUser : sysUsers) {
                if (sysUser.getRebatesFlag() == 0) {
                    sysUser.setMemberLeve(rightMemberLevel);
                    sysUserMapper.updateById(sysUser);
                }

            }
        }
    }

    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        String date = DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", c.getTime());
        System.out.println("date = " + date);
    }
}
